/*
 * Tencent is pleased to support the open source community by making QMUI_Android available.
 *
 * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
 *
 * Licensed under the MIT License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/MIT
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.allenlee.mvphelper.base;

import android.content.Context;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;

import com.allenlee.mvphelper.R;
import com.allenlee.mvphelper.util.NavigationHelper;
import com.allenlee.mvphelper.util.ToastHelper;
import com.qmuiteam.qmui.arch.QMUIFragmentActivity;
import com.qmuiteam.qmui.util.QMUIKeyboardHelper;
import com.qmuiteam.qmui.widget.dialog.QMUIDialog;
import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction;
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.uber.autodispose.AutoDispose;
import com.uber.autodispose.AutoDisposeConverter;
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider;

import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * Created by lifei on 2018/1/7.
 */

public abstract class BaseFragmentActivity<P extends IBasePresenter> extends QMUIFragmentActivity implements IBaseView {

    protected P mPresenter;

    private Disposable disposable;

    private QMUITipDialog mLoadingDialog;

    protected abstract void initLayout(@Nullable Bundle savedInstanceState);

    protected abstract void initViews();

    protected abstract void afterInitView();

    protected abstract P setPresenter();

    protected <T extends View> T $(@IdRes int viewId) {
        return findViewById(viewId);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initLayout(savedInstanceState);

        // 实例化和绑定 P 层
        mPresenter = setPresenter();
        if (mPresenter != null) {
            mPresenter.attach(this);
        }

        initViews();
        afterInitView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }

        // 解绑，避免内存泄漏
        if (mPresenter != null) {
            mPresenter.detach();
            mPresenter = null;
        }
    }

    @Override
    public Context getContext() {
        return this;
    }

    /**
     * 绑定生命周期 防止MVP内存泄漏
     * @param <T>
     * @return
     */
    @Override
    public <T> AutoDisposeConverter<T> bindAutoDispose() {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider
            .from(this, Lifecycle.Event.ON_DESTROY));
    }

    protected void requestPermissions(String... permissions) {
        RxPermissions rxPermissions = new RxPermissions(this);
        disposable = rxPermissions
            .requestEachCombined(permissions)
            .subscribe(permission -> { // will emit 1 Permission object
                if (permission.shouldShowRequestPermissionRationale) {
                    // At least one denied permission without ask never again
                    permissionDenied();
                } else if (!permission.granted) {
                    // At least one denied permission with ask never again
                    // Need to go to the settings
                    showLongMessageDialog();
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    showToast("onError");
                    throwable.printStackTrace();
                }
            });
    }

    private void showLongMessageDialog() {
        QMUIDialog qmuiDialog = new QMUIDialog.MessageDialogBuilder(this)
            .setTitle("权限申请")
            .setMessage("当前应用缺少必要权限。\n\n请点击\"设置\"-\"权限\"-打开所需权限。")
            .addAction("取消", new QMUIDialogAction.ActionListener() {
                @Override
                public void onClick(QMUIDialog dialog, int index) {
                    dialog.dismiss();
                    permissionDenied();
                }
            })
            .addAction("设置", new QMUIDialogAction.ActionListener() {
                @Override
                public void onClick(QMUIDialog dialog, int index) {
                    dialog.dismiss();
                    NavigationHelper.startAppSettings(BaseFragmentActivity.this);
                }
            })
            .create(R.style.QMUI_Dialog);
        qmuiDialog.setCancelable(false);
        qmuiDialog.show();
    }

    /* ***************************************隐藏软键盘************************************************** */

    /**
     * 点击空白区域隐藏键盘.
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {  //把操作放在用户点击的时候
            View v = getCurrentFocus();      //得到当前页面的焦点,ps:有输入框的页面焦点一般会被输入框占据
            if (isShouldHideKeyboard(v, ev)) { //判断用户点击的是否是输入框以外的区域
                // hideKeyboard(v.getWindowToken());   //收起键盘
                QMUIKeyboardHelper.hideKeyboard(v);
            }
        }

        return super.dispatchTouchEvent(ev);
    }

    /**
     * 根据EditText所在坐标和用户点击的坐标相对比，来判断是否隐藏键盘，因为当用户点击EditText时则不能隐藏
     * @param v
     * @param event
     * @return
     */
    private boolean isShouldHideKeyboard(View v, MotionEvent event) {
        if (v instanceof EditText) {  //判断得到的焦点控件是否包含EditText
            int[] l = {0, 0};
            v.getLocationInWindow(l);
            int left = l[0],    //得到输入框在屏幕中上下左右的位置
                top = l[1],
                bottom = top + v.getHeight(),
                right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right
                && event.getY() > top && event.getY() < bottom) {
                // 点击位置如果是EditText的区域，忽略它，不收起键盘。
                return false;
            } else {
                return true;
            }
        }
        // 如果焦点不是EditText则忽略
        return false;
    }

    /* ***************************************隐藏软键盘************************************************** */

    @Override
    public void permissionGranted() {
        // 处理权限被允许
    }

    @Override
    public void permissionDenied() {
        // 处理权限被拒绝
    }

    public void showToast(String msg) {
        ToastHelper.showToast(this, msg);
    }

    public void showToast(int msgId) {
        ToastHelper.showToast(this, msgId);
    }

    public void showLongToast(String msg) {
        ToastHelper.showLongToast(this, msg);
    }

    public void showLongToast(int msgId) {
        ToastHelper.showLongToast(this, msgId);
    }

    public void showLoading(String text) {
        if (mLoadingDialog == null) {
            mLoadingDialog = new QMUITipDialog.Builder(this)
                .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
                .setTipWord(text)
                .create();
        }
        if (!mLoadingDialog.isShowing()) {
            mLoadingDialog.show();
        }
    }

    public void hideLoading() {
        if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
            mLoadingDialog.dismiss();
        }
    }
}
